package com.icedata.sika.bridge

import com.icedata.sika.util.Logger
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.*
import net.mamoe.mirai.contact.MemberPermission.*
import java.util.*

/**
 * Sika中发送对象的抽象类
 *
 * 有两个实现：
 *
 * [SikaUserContact] 用户对象
 *
 * [SikaGroupContact] 群对象
 */
open class SikaContact(val contact: Contact) {
    /**
     * 发送对象的id（群号或者QQ号）
     */
    val id: Long by lazy {
        return@lazy contact.id
    }

    /**
     * 发送对象的名字（群名或者用户昵称）
     */
    val name: String by lazy {
        when (contact) {
            is User -> return@lazy contact.nick
            is Group -> return@lazy contact.name
            else -> return@lazy ""
        }
    }

    /**
     * 发送一条消息链
     *
     * @param messageChain 需要发送的消息链
     */
    @UserSikaAPI
    @MiraiBasedAPI
    fun sendMessage(messageChain: SikaMessageChain) {
        GlobalScope.launch(Dispatchers.IO) {
            contact.sendMessage(messageChain.miraiMessageChain)
        }
        Logger.logSend(messageChain, this)
    }

    @UserSikaAPI
    fun sendMessage(builder: SikaMessageChainBuilder) {
        sendMessage(builder.build())
    }

    @UserSikaAPI
    fun sendMessage(message: String) {
        val builder = SikaMessageChainBuilder()
        builder.add(SikaPlainMessage(message))
        sendMessage(builder.build())
    }

    @UserSikaAPI
    fun sendMessage(message: SikaSingleMessage) {
        val builder = SikaMessageChainBuilder()
        builder.add(message)
        sendMessage(builder.build())
    }

    @UserSikaAPI
    fun sendMessage(message: Any) {
        sendMessage(message.toString())
    }

    /**
     * 撤回一条消息
     *
     * @param message SikaMessageChain 需要撤回的消息句柄
     */
    @UserSikaAPI
    @MiraiBasedAPI
    suspend fun recallMessage(message: SikaMessageChain) {
        contact.recallMessage(message.miraiMessageChain)
    }
}

/**
 * 用户对象
 */
class SikaUserContact(val groupName: String, contact: User) : SikaContact(contact) {
    constructor(id: Long) : this(
        Bot.instances[0].getFriendOrFail(id).nick,
        Bot.instances[0].getFriendOrFail(id)
    )
}

/**
 * 群对象
 */
class SikaGroupContact(contact: Group) : SikaContact(contact) {
    constructor(id: Long) : this(Bot.instances[0].getGroup(id)!!)

    class SikaGroupMember(contact: Member): SikaContact(contact) {
        enum class Permission{
            Member, Admin, Owner
        }

        suspend fun mute(muteTime: Int) {
            contact as Member
            contact.mute(muteTime)
        }

        fun getPermission(): Permission {
            contact as Member
            return when (contact.permission) {
                MEMBER -> Permission.Member
                ADMINISTRATOR -> Permission.Admin
                OWNER -> Permission.Owner
            }
        }
    }

    fun getUserAsMember(id: Long): SikaGroupMember {
        return SikaGroupMember((contact as Group)[id]!!)
    }

    /**
     * 获取群成员列表
     *
     * @return LinkedList<SikaUserContact> 群成员列表
     */
    @MiraiBasedAPI
    fun getUsers(): LinkedList<SikaUserContact> {
        contact as Group
        return LinkedList<SikaUserContact>().apply {
            contact.members.forEach {
                this.add(SikaUserContact(it.nick, it))
            }
        }
    }

    @MiraiBasedAPI
    fun getBotAsMember(): SikaGroupMember {
        contact as Group
        return SikaGroupMember(contact.botAsMember)
    }

    /**
     * 禁言某个群成员
     *
     * @param id Long 群成员id
     * @param muteTime Int 禁言时间（s）
     */
    @MiraiBasedAPI
    suspend fun muteUser(id: Long, muteTime: Int) {
        contact as Group
        contact.getMember(id)?.mute(muteTime)
    }

    suspend fun demuteUser(id: Long) {
        contact as Group
        contact.getMember(id)?.unmute()
    }
}